package com.cn.serverline.lineicp.workshopPlan.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.stylefeng.roses.kernel.rule.exception.base.ServiceException;
import cn.stylefeng.roses.kernel.rule.pojo.response.ResponseData;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cn.serverline.lineicp.workshopPlan.entity.LineAssembleBatchSplit;
import com.cn.serverline.lineicp.workshopPlan.entity.WeekStageDaysTasks;
import com.cn.serverline.lineicp.workshopPlan.entity.request.WeekStageDaysTasksRequest;
import com.cn.serverline.lineicp.workshopPlan.entity.request.WeeklyTimeRequest;
import com.cn.serverline.lineicp.workshopPlan.enums.*;
import com.cn.serverline.lineicp.workshopPlan.mapper.WeekStageDaysTasksMapper;
import com.cn.serverline.lineicp.workshopPlan.service.WeekStageDaysTasksService;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import java.sql.Timestamp;

/**
 * 周计划详情，部装/总装
 */
@Service("PlanWeekStageDaysTasksServiceImpl")
public class WeekStageDaysTasksServiceImpl extends ServiceImpl<WeekStageDaysTasksMapper, WeekStageDaysTasks> implements WeekStageDaysTasksService {

    @Resource
    private WeekStageDaysTasksMapper weekStageDaysTasksMapper;

    @Resource
    private LineAssembleBatchSplitServiceImpl lineAssembleBatchSplitService;

    @Override
    public List<WeeklyTimeRequest> findWeek(WeekStageDaysTasksRequest planWeekStageDaysTasksVo) {
        HashMap<Integer, List<Timestamp>> map = getWeeklyTime(planWeekStageDaysTasksVo.getYear().intValue(), planWeekStageDaysTasksVo.getMonth().intValue(), 1);
        List<WeeklyTimeRequest> weeklyTimeVos = new ArrayList<>();
        for (Integer integer : map.keySet()) {
            WeeklyTimeRequest weeklyTimeVo = new WeeklyTimeRequest();
            List<Timestamp> timestamps = map.get(integer);
            LambdaQueryWrapper<WeekStageDaysTasks> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(WeekStageDaysTasks::getWeekStageCode, planWeekStageDaysTasksVo.getWeekPlan());
            queryWrapper.isNull(WeekStageDaysTasks::getParentId);
            DateTime startDateTime = DateUtil.parse(DateUtil.format(timestamps.get(0), "yyyy-MM-dd"), "yyyy-MM-dd");
            DateTime endDateTime = DateUtil.parse(DateUtil.format(timestamps.get(1), "yyyy-MM-dd"), "yyyy-MM-dd");
            //根据周计划下发历史查询
            queryWrapper.eq(WeekStageDaysTasks::getPlanWeekStageDaysHistoryI, planWeekStageDaysTasksVo.getPlanWeekStageDaysHistoryI());

            queryWrapper.and(e -> {
                e.ge(WeekStageDaysTasks::getStartDate, new Timestamp(startDateTime.getTime()))
                        .le(WeekStageDaysTasks::getStartDate, new Timestamp(endDateTime.getTime()))
                        .or()
                        .ge(WeekStageDaysTasks::getEndDate, new Timestamp(startDateTime.getTime()))
                        .le(WeekStageDaysTasks::getEndDate, new Timestamp(endDateTime.getTime()));
            });

            List<WeekStageDaysTasks> stageDaysTasks = weekStageDaysTasksMapper.selectList(queryWrapper);
            weeklyTimeVo.setWeek(integer);
            weeklyTimeVo.setSize((long) stageDaysTasks.size());
            weeklyTimeVos.add(weeklyTimeVo);
        }
        return weeklyTimeVos;
    }


    /**
     * 周总装批次拆分
     *
     * @param planWeekStageDaysTasks 请求参数
     */
    @Override
    public void batchSplit(List<WeekStageDaysTasks> planWeekStageDaysTasks) {
        planWeekStageDaysTasks.stream().forEach(e -> {
            Long id = e.getId();
            Long prodConfigurationId = e.getProdConfigurationId();
            if (prodConfigurationId == null) {
                throw new ServiceException(RolingPlanException.PROD_NOT_NULL);
            }
            if (id == null) {
                throw new ServiceException(RolingPlanException.ID_NOT_NULL);
            }
        });
        // 创建一个Stream流，从planWeekStageDaysTasks集合中
        List<Long> collect = planWeekStageDaysTasks.stream()
                // 使用map操作，将每个WeekStageDaysTasks对象映射成其ID属性
                .map(WeekStageDaysTasks::getId)
                // 使用collect操作，将流中的元素收集到一个新的List集合中
                .collect(Collectors.toList());
        // 检查收集到的ID列表的大小是否为0
        if (collect.size() == 0) {
            // 如果列表为空，即没有元素，直接返回，不执行后续代码
        }
        this.updateBatchById(planWeekStageDaysTasks);
        List<WeekStageDaysTasks> weekStageDaysTasks = this.listByIds(collect);
        List<LineAssembleBatchSplit> lineAssembleBatchSplits = new ArrayList<>();
        for (WeekStageDaysTasks weekStageDaysTask : weekStageDaysTasks) {
            //修改其他部装节点
            LambdaUpdateWrapper<WeekStageDaysTasks> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(WeekStageDaysTasks::getPlanWeekStageDaysHistoryI, weekStageDaysTask.getPlanWeekStageDaysHistoryI());
            updateWrapper.eq(WeekStageDaysTasks::getWeekStageCode, DigitEnum.FOUR.getState());
            updateWrapper.set(WeekStageDaysTasks::getProdConfigurationId, weekStageDaysTask.getProdConfigurationId());
            this.update(updateWrapper);

            LineAssembleBatchSplit lineAssembleBatchSplit = new LineAssembleBatchSplit();
            //车间下发周计划任务明细id
            lineAssembleBatchSplit.setPlanWeekStageDaysTasksId(weekStageDaysTask.getId());
            //产品构型id
            lineAssembleBatchSplit.setProdConfigurationId(weekStageDaysTask.getProdConfigurationId());
            //计划批次数量
            lineAssembleBatchSplit.setPlanQuantity(weekStageDaysTask.getPlanQuantity());
            //物料在库情况
            lineAssembleBatchSplit.setMaterialComplete(ImportDistributeEnum.COMPLETE.getState());
            //生成状态
            lineAssembleBatchSplit.setBuildStatus(LinePlanEnum.UNSCHEDULED_PRODUCTION.getState());
            Long planQuantity = weekStageDaysTask.getPlanQuantity();
            long count = planQuantity % 5 == 0 ? planQuantity / 5 : planQuantity / 5 + 1;
            String lotNo = weekStageDaysTask.getLotNo();
            for (int i = 1; i <= count; i++) {
                LineAssembleBatchSplit batchSplit = new LineAssembleBatchSplit();
                BeanUtil.copyProperties(lineAssembleBatchSplit, batchSplit);
                String smallBatchNumber = "";
                //批次数量
                if (i == count) {
                    batchSplit.setBatchQuantity(planQuantity % 5 == 0 ? 5L : planQuantity % 5);
                } else {
                    batchSplit.setBatchQuantity(DigitEnum.FIVE.getState().longValue());
                }
                //小批次号
                if (i < 10) {
                    smallBatchNumber = lotNo + "-0" + i;
                } else {
                    smallBatchNumber = lotNo + "-" + i;
                }
                batchSplit.setSmallBatchNumber(smallBatchNumber);
                lineAssembleBatchSplits.add(batchSplit);
            }
        }
        lineAssembleBatchSplitService.saveBatch(lineAssembleBatchSplits);
        //修改拆分状态
        List<Long> ids = weekStageDaysTasks.stream().map(WeekStageDaysTasks::getId).collect(Collectors.toList());
        LambdaUpdateWrapper<WeekStageDaysTasks> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(WeekStageDaysTasks::getSplitStatus, LinePlanEnum.SPLIT.getState());
        wrapper.in(WeekStageDaysTasks::getId, ids);
        this.update(wrapper);
    }

    /**
     * 周计划详情
     * @param weekStageDaysTasksRequest 请求参数
     * @return
     */
    @Override
    public HashMap<String, Object> findList(WeekStageDaysTasksRequest weekStageDaysTasksRequest) {
        // 初始化结果映射
        HashMap<String, Object> resultmap = new HashMap<>();

        // 获取周时间映射
        HashMap<Integer, List<Timestamp>> map = getWeeklyTime(
                weekStageDaysTasksRequest.getYear().intValue(),
                weekStageDaysTasksRequest.getMonth().intValue(),
                weekStageDaysTasksRequest.getWeek()
        );
        List<Timestamp> weeklyTime = map.get(weekStageDaysTasksRequest.getWeek());

        // 构建查询条件
        LambdaQueryWrapper<WeekStageDaysTasks> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(WeekStageDaysTasks::getWeekStageCode, weekStageDaysTasksRequest.getWeekPlan())
                .ge(WeekStageDaysTasks::getStartDate, new Timestamp(weeklyTime.get(0).getTime()))
                .le(WeekStageDaysTasks::getStartDate, new Timestamp(weeklyTime.get(1).getTime()))
                .or()
                .ge(WeekStageDaysTasks::getEndDate, new Timestamp(weeklyTime.get(0).getTime()))
                .le(WeekStageDaysTasks::getEndDate, new Timestamp(weeklyTime.get(1).getTime()))
                .isNull(WeekStageDaysTasks::getParentId)
                .eq(WeekStageDaysTasks::getPlanWeekStageDaysHistoryI, weekStageDaysTasksRequest.getPlanWeekStageDaysHistoryI());
        // 执行查询
        List<WeekStageDaysTasks> weekStageDaysTasks = weekStageDaysTasksMapper.selectList(wrapper);

        // 数据转换
        List<WeekStageDaysTasksRequest> weekStageDaysTasksVos = BeanUtil.copyToList(weekStageDaysTasks, WeekStageDaysTasksRequest.class);

        // 处理特定逻辑
        for (WeekStageDaysTasksRequest weekStageDaysTasksVo : weekStageDaysTasksVos) {
            if (weekStageDaysTasksVo.getLotNo().contains(lotNoEnum.YT.getCode())) {
                weekStageDaysTasksVo.setPreinvestmentQuantity(weekStageDaysTasksVo.getPlanQuantity());
                weekStageDaysTasksVo.setPlanQuantity(null);
            }
        }

        // 结果存储与返回
        resultmap.put("data", weekStageDaysTasksVos);
        return resultmap;
    }

    /**
     * 每周数量
     * @param year 年
     * @param month 月
     * @param findWeek 周
     * @return
     */
    public HashMap<Integer, List<Timestamp>> getWeeklyTime(int year, int month, int findWeek) {
        HashMap<Integer, List<Timestamp>> map = new HashMap<>();
        Calendar calendar = Calendar.getInstance();
        List<Timestamp> dates = new ArrayList<>();
        calendar.set(year, month - 1, 1);
        int days = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        dates.add(new Timestamp(calendar.getTime().getTime()));
        int week = 1;
        for (int i = 1; i <= days; i++) {
            calendar.set(year, month - 1, i);
            int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
            if (dayOfWeek - 1 == 0) {
                dates.add(new Timestamp(calendar.getTime().getTime()));
                map.put(week, dates);
                if (i != days) {
                    dates = new ArrayList<>();
                    calendar.set(year, month - 1, i + 1);
                    dates.add(new Timestamp(calendar.getTime().getTime()));
                    week++;
                }
            }
        }
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        if (dayOfWeek - 1 != 0) {
            dates.add(new Timestamp(calendar.getTime().getTime()));
            map.put(week, dates);
        }
        return map;
    }
}
